import {
  type BoundingBox,
  GraphicObject,
  GraphicType,
  type Point,
  type ViewTransform,
} from '../GraphicObject';
import TransformManager from '../TransformManager';
import type { GraphicObjectData } from '../types';

export class Rectangle extends GraphicObject {
  public width: number;
  public height: number;
  public cornerRadius?: number;
  static create: (
    width: number,
    height: number,
    options?: {
      transform?: any;
      style?: any;
      layerId?: string;
      cornerRadius?: number;
    },
  ) => Rectangle;

  constructor(
    width: number,
    height: number,
    transform = GraphicObject.defaultTransform(),
    style = GraphicObject.defaultStyle(),
    layerId = 'default',
    cornerRadius?: number,
  ) {
    super(GraphicType.RECTANGLE, transform, style, layerId);
    this.width = width;
    this.height = height;
    this.cornerRadius = cornerRadius;
  }

  draw(ctx: CanvasRenderingContext2D, viewTransform: ViewTransform): void {
    ctx.save();

    // 应用视图变换
    ctx.translate(viewTransform.offset.x, viewTransform.offset.y);
    ctx.scale(viewTransform.scale, viewTransform.scale);
    ctx.rotate(viewTransform.rotation);

    // 应用对象变换
    ctx.translate(this.transform.position.x, this.transform.position.y);
    ctx.rotate(this.transform.rotation);
    ctx.scale(this.transform.scale.x, this.transform.scale.y);

    // 设置样式
    if (this.style.fillColor) {
      ctx.fillStyle = this.style.fillColor;
    }
    if (this.style.strokeColor) {
      ctx.strokeStyle = this.style.strokeColor;
    }
    if (this.style.strokeWidth) {
      ctx.lineWidth = this.style.strokeWidth / viewTransform.scale;
    }
    if (this.style.opacity) {
      ctx.globalAlpha = this.style.opacity;
    }
    if (this.style.lineDash) {
      ctx.setLineDash(this.style.lineDash);
    }

    // 绘制矩形
    ctx.beginPath();

    if (this.cornerRadius && this.cornerRadius > 0) {
      // 圆角矩形
      const x = -this.width * this.transform.anchor.x;
      const y = -this.height * this.transform.anchor.y;
      const width = this.width;
      const height = this.height;
      const radius = this.cornerRadius;

      ctx.moveTo(x + radius, y);
      ctx.lineTo(x + width - radius, y);
      ctx.arcTo(x + width, y, x + width, y + radius, radius);
      ctx.lineTo(x + width, y + height - radius);
      ctx.arcTo(x + width, y + height, x + width - radius, y + height, radius);
      ctx.lineTo(x + radius, y + height);
      ctx.arcTo(x, y + height, x, y + height - radius, radius);
      ctx.lineTo(x, y + radius);
      ctx.arcTo(x, y, x + radius, y, radius);
      ctx.closePath();
    } else {
      // 直角矩形
      const x = -this.width * this.transform.anchor.x;
      const y = -this.height * this.transform.anchor.y;
      ctx.rect(x, y, this.width, this.height);
    }

    // 填充和描边
    if (this.style.fillColor) {
      ctx.fill();
    }
    if (this.style.strokeColor && this.style.strokeWidth) {
      ctx.stroke();
    }

    ctx.restore();
  }

  contains(point: Point): boolean {
    // 将世界坐标转换为对象局部坐标
    const localPoint = TransformManager.worldToLocal(point, this.transform);

    const x = -this.width * this.transform.anchor.x;
    const y = -this.height * this.transform.anchor.y;

    return (
      localPoint.x >= x &&
      localPoint.x <= x + this.width &&
      localPoint.y >= y &&
      localPoint.y <= y + this.height
    );
  }

  getBoundingBox(): BoundingBox {
    const x = this.transform.position.x - this.width * this.transform.anchor.x;
    const y = this.transform.position.y - this.height * this.transform.anchor.y;

    return {
      x,
      y,
      width: this.width * this.transform.scale.x,
      height: this.height * this.transform.scale.y,
    };
  }

  /**
   * 序列化对象数据
   */
  serialize(): GraphicObjectData {
    return {
      id: this.id,
      type: this.type,
      transform: { ...this.transform },
      style: { ...this.style },
      layerId: this.layerId,
      width: this.width,
      height: this.height,
      cornerRadius: this.cornerRadius,
    };
  }
}

// 静态创建方法
Rectangle.create = (
  width: number,
  height: number,
  options?: {
    transform?: any;
    style?: any;
    layerId?: string;
    cornerRadius?: number;
  },
) => {
  return new Rectangle(
    width,
    height,
    options?.transform,
    options?.style,
    options?.layerId,
    options?.cornerRadius,
  );
};
